// Mob.java
//
// The basic Mob class. It's a very customizable framework!

import java.util.ArrayList;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
import java.nio.*;
import java.util.Random;

public class Mob
{
    // Properties of this Mob
    private int num; // The ID number of this mob
    private String name;
    private String desc;
    private int invCap;
    // Other stuff
    private BufferedImage img;
    private BufferedReader reader;
    private Random generator;
    // The tile containing this Mob
    private Tile tile;
    
    // the distance at which this Mob will become aware of things
    private int awareness;
    // an Array of tiles the mob is aware of
    private ArrayList<Tile> awareTiles;
    
    // The items the mob has equipped/in inventory
    private ArrayList<Item> inventory;
    private Item head;
    private Item body;
    private Item rHand;   // Active hand
    private Item lHand;   // Offhand
    private Item legs;
    private Item feet;
    private Item accessory;
    
    public Mob(int mobNum, Tile passedTile)
    {           
        try
	{
            // Set ID number and default values
            num = mobNum;
            tile = passedTile;
            inventory = new ArrayList<Item>();
            invCap = 8;
            name = "Nothing";
            desc = "This is the lack of a mob! ERROR: This shouldn't appear through normal gameplay!";
            img = ImageIO.read(new File("Mobs\\Images\\Blank.png"));
            head = new Item(0);
            body = new Item(0);
            rHand = new Item(0);
            lHand = new Item(0);
            legs = new Item(0);
            feet = new Item(0);
            accessory = new Item(0);
            awareness = 0;
            
            // Reads each line from the mob's config file into a temporary string,
            // and then sets the mob's variables based on that string
            String file = "Mobs\\" + num + ".txt";
            reader = new BufferedReader(new FileReader(file));
            String temp;
            String cat, value;
            while(true)
            {
                temp = reader.readLine();
                if (temp.contains("END")) {break;} // ugh I really hate this 
                cat = temp.substring(0, temp.indexOf("="));
                value = temp.substring(temp.indexOf("=") + 1);
                            
                switch (cat)
                {
                    case "Name":
                    {
                        name = value;
                        break;
                    }
                    case "Desc":
                    {
                        desc = value;
                        break;
                    }
                    case "Image":
                    {
                        img = ImageIO.read(new File(value));
                        break;
                    }
                    case "InvCap":
                    {
                        invCap = Integer.valueOf(value);
                        break;
                    }
                    case "Awareness":
                    {
                        awareness = Integer.valueOf(value);
                        break;
                    }
                    default:
                    {
                        break;
                    }
                }
            }
            reader.close();
        }
        catch(IOException e)
        {
            System.out.println("Uh oh! Something broke with the file reading!");
            System.out.println(e);
        }
        generator = new Random();
    }

    public void display(int x, int y, Graphics g)
    {
        g.drawImage(img, x, y, null);
        legs.displayEquip(x, y, g);
        body.displayEquip(x, y, g);
        head.displayEquip(x, y, g);
        feet.displayEquip(x, y, g);
        accessory.displayEquip(x, y, g);
        lHand.displayEquip(x, y, g);
        rHand.displayEquip(x, y, g);
    }

    public void tick()
    {
        tile.queue(this);
    }

    public void move()
    {
        wander();
    }
    
    public ArrayList<Tile> getAwareTiles()
    {
        ArrayList<Tile> t = tile.getTilesInRadius(awareness);
        t.add(tile);
        return t;
    }

    // INVENTORY METHODS
    // Adding and Removing
    public void addItem(Item i)
    {
        if (inventory.size() >= invCap)
        {
            return;
        }
        else
        {
            inventory.add(i);
        }
    }
    
    public void removeItem(int itemIndex)
    {
        inventory.remove(itemIndex);
    }

    // Only removes the first occurance of i!
    public void removeItem(Item i)
    {
        inventory.remove(i);
    }
    
    // Remove the item from mob's inventory and add it to the tile
    public void drop(Item i)
    {
        if (i.getNum() != 0)
        {
            inventory.remove(i);
            tile.addItem(i);
        }
    }
    
    // Equipping items
    public void equip(Item i)
    {
        if (i.isEquippable())
        {
            String type = i.getType();
            switch(type)
            {
                case "Head":
                {
                    unequipHead();
                    head = i;
                    break;
                }
                case "Body":
                {
                    unequipBody();
                    body = i;
                    break;
                }
                case "Legs":
                {
                    unequipLegs();
                    legs = i;
                    break;
                }
                case "Feet":
                {
                    unequipFeet();
                    feet = i;
                    break;
                }
                case "Accessory":
                {
                    unequipAccessory();
                    accessory = i;
                    break;
                }
                case "Active":
                {
                    unequipActive();
                    rHand = i;
                    break;
                }
                case "Off":
                {
                    unequipOff();
                    lHand = i;
                    break;
                }
                default:
                {
                    System.out.println("ERROR: Equippable item with invalid type.\n" + i);
                    break;
                }
            }
        }
        else
        {
            System.out.println("You cannot equip " + i.getName());
        }
    }
    // Equip item and remove it from inventory
    public void equipFromInv(Item i)
    {
        equip(i);
        removeItem(i);
    }
    // remove an item from the mob's equipped items, add it to inventory
    public void unequipHead()
    {
        if (head.getNum() != 0)
        {
            inventory.add(head);
            head = new Item(0);
        }
    }
    public void unequipBody()
    {
        if (body.getNum() != 0)
        {
            inventory.add(body);
            body = new Item(0);
        }
    }
    public void unequipLegs()
    {
        if (legs.getNum() != 0)
        {
            inventory.add(legs);
            legs = new Item(0);
        }
    }
    public void unequipFeet()
    {
        if (feet.getNum() != 0)
        {
            inventory.add(feet);
            feet = new Item(0);
        }
    }
    public void unequipAccessory()
    {
        if (accessory.getNum() != 0)
        {
            inventory.add(accessory);
            accessory = new Item(0);
        }
    }
    public void unequipActive()
    {
        if (rHand.getNum() != 0)
        {
            inventory.add(rHand);
            rHand = new Item(0);
        }
    }
    public void unequipOff()
    {
        if (lHand.getNum() != 0)
        {
            inventory.add(lHand);
            lHand = new Item(0);
        }
    }
    
    // Examine the mob
    public void examine()
    {
        System.out.println("It is " + name + ". " + 
                            desc.substring(0,1).toUpperCase() + desc.substring(1));
        if(!(rHand.getNum() == 0))
        {
            System.out.println("It is wielding " + rHand.getName());
        }
        if(!(lHand.getNum() == 0))
        {
            System.out.println("It is holding " + lHand.getName());
        }
        if(!(head.getNum() == 0))
        {
            System.out.println("It is wearing " + head.getName());
        }
        if(!(legs.getNum() == 0))
        {
            System.out.println("It is wearing " + legs.getName());
        }
        if(!(body.getNum() == 0))
        {
            System.out.println("It is wearing " + body.getName());
        }
        if(!(feet.getNum() == 0))
        {
            System.out.println("It is wearing " + feet.getName());
        }
        if(!(accessory.getNum() == 0))
        {
            System.out.println("It is wearing " + accessory.getName());
        }
    }

    // MOVEMENT METHODS
    // Generic methods
    public void wander()
    {
        ArrayList<Tile> moveOptions = getMovableLocs();
        int temp = (int) (generator.nextDouble() * (moveOptions.size()));
        tile.moveMobTo(0, moveOptions.get(temp));
    }
    
    // Gets all available movement locations
    public ArrayList<Tile> getMovableLocs()
    {
        ArrayList<Tile> movable = new ArrayList<Tile>();
        for(Tile t : tile.getSurroundingTiles())
        {
            if(t.isPassable())
            {
                movable.add(t);
            }
        }
        // not moving is an option too
        movable.add(tile);
        return movable;
    }

    // Specific methods
    public void moveNorth()
    {
        tile.moveMobTo(0, tile.getX(), tile.getY() - 1);
    }

    public void moveNorthEast()
    {
        tile.moveMobTo(0, tile.getX() + 1, tile.getY() - 1);
    }

    public void moveEast()
    {
        tile.moveMobTo(0, tile.getX() + 1, tile.getY());
    }

    public void moveSouthEast()
    {
        tile.moveMobTo(0, tile.getX() + 1, tile.getY() + 1);
    }

    public void moveSouth()
    {
        tile.moveMobTo(0, tile.getX(), tile.getY() + 1);
    }

    public void moveSouthWest()
    {
        tile.moveMobTo(0, tile.getX() - 1, tile.getY() + 1);
    }

    public void moveWest()
    {
        tile.moveMobTo(0, tile.getX() - 1, tile.getY());
    }

    public void moveNorthWest()
    {
        tile.moveMobTo(0, tile.getX() - 1, tile.getY() - 1);
    }

    public void hold()
    {
        return;
    }

    // GET AND SET METHODS
    public int getNum()
    {
        return num;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String newName)
    {
        name = newName;
    }

    public String getDesc()
    {
        return desc;
    }

    public void setDesc(String newDesc)
    {
        desc = newDesc;
    }

    public void setImg(BufferedImage newImg)
    {
        img = newImg;
    }

    public void setTile(Tile newTile)
    {
        tile = newTile;
    }

    // END GETS/SETS

    public String toString()
    {
        return ("///////////////" +
                "\n//Class: Mob" +
                "\n//ID Number: " + num +
		"\n//Name: " + name +
		"\n//Description: " + desc +
                "\n//Inventory Capacity: " + invCap +
		"\n///////////////");
    }
}